package com.atjava.nebula.web.security;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.util.AntPathMatcher;

import com.atjava.nebula.frames.auth.service.AuthService;
import com.atjava.nebula.frames.resources.SysResource;
import com.atjava.nebula.frames.role.SysRole;
import com.atjava.nebula.frames.user.service.UserService;

/** 
 * @author kyo 
 */ 
public class NebulaFilterInvocationSecurityMetadataSource 
	implements FilterInvocationSecurityMetadataSource {

	private AuthService authService;
	private Map<String, Collection<ConfigAttribute>> resourceMap = null;
	private AntPathMatcher urlMatcher = new AntPathMatcher();

	public NebulaFilterInvocationSecurityMetadataSource
		(UserService userService,AuthService authService) {
		
		this.authService = authService;
		loadResourcesDefine();
	}

	private void loadResourcesDefine() {
		resourceMap = new HashMap<String, Collection<ConfigAttribute>>();
		
		List<SysRole> roles = authService.getAllRoles();
		for (int i = 0; i < roles.size(); i++) {
			
			SysRole role = roles.get(i);
			List<SysResource> resources = authService.getResourcesByRole(role.getPkid());
			
			for (int n = 0; n < resources.size(); n++) {
				
				SysResource resource = resources.get(n);
				Collection<ConfigAttribute> configAttributes = null;
				ConfigAttribute configAttribute = new SecurityConfig(String.valueOf(role.getPkid()));
				
				if (resourceMap.containsKey(resource.getUrl())) {
					configAttributes = resourceMap.get(resource.getUrl());
					configAttributes.add(configAttribute);
				} else {
					configAttributes = new ArrayList<ConfigAttribute>();
					configAttributes.add(configAttribute);
					resourceMap.put(resource.getUrl(), configAttributes);
				}
			}
		}
	}
	
	public Collection<ConfigAttribute> getAttributes(Object obj)throws IllegalArgumentException {
		
		//remove request url parameters
		String requestUrl = ((FilterInvocation) obj).getRequestUrl();
		/*int firstQuesMarkIndex = requestUrl.indexOf("?");
		if (firstQuesMarkIndex != -1) {
			requestUrl = requestUrl.substring(0, firstQuesMarkIndex);
		}*/
		
		List<ConfigAttribute> attributes = new ArrayList<ConfigAttribute>();
		
		//find configuration attribute in resource map by request url 
		Iterator<String> it = resourceMap.keySet().iterator();
		while (it.hasNext()) {
			String resourceUrl = it.next();
			if (urlMatcher.match(resourceUrl, requestUrl)){
				attributes.addAll(resourceMap.get(resourceUrl));
			}
		}
		return attributes;
	}

	public boolean supports(Class<?> arg0) {
		return true;
	}
	
	public Collection<ConfigAttribute> getAllConfigAttributes() {
		return null;
	}

}
